﻿using System;
using System.IO;
using System.Text;

namespace RC4Encryption
{
    public class Program
    {
        private const string FileToEncode = @"C:\Windows\System32\notepad.exe";
        private const string EncodedFileName = @"Encoded File";
        private const string DecodedFileName = @"Decoded File.exe";

        private static void RC4(ref Byte[] bytes, Byte[] key)
        {
            Byte[] s = new Byte[256];
            Byte[] k = new Byte[256];
            Byte temp;
            int i, j;

            for (i = 0; i < 256; i++)
            {
                s[i] = (Byte)i;
                k[i] = key[i % key.GetLength(0)];
            }

            j = 0;
            for (i = 0; i < 256; i++)
            {
                j = (j + s[i] + k[i]) % 256;
                temp = s[i];
                s[i] = s[j];
                s[j] = temp;
            }

            i = j = 0;
            for (int x = 0; x < bytes.GetLength(0); x++)
            {
                i = (i + 1) % 256;
                j = (j + s[i]) % 256;
                temp = s[i];
                s[i] = s[j];
                s[j] = temp;
                int t = (s[i] + s[j]) % 256;
                bytes[x] ^= s[t];
            }
        }

        private static byte[] ReadInputFile(string fileName)
        {
            byte[] bytes;
            using (var reader = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                bytes = new byte[reader.Length];
                reader.Read(bytes, 0, (int)reader.Length);
            }
            return bytes;
        }

        private static void WriteOutputFile(string fileName, byte[] bytes)
        {
            using (var writer = new FileStream(fileName, FileMode.Create, FileAccess.Write))
            {
                writer.Write(bytes, 0, bytes.Length);
            }
        }

        public static void PrintBytes(byte[] bytes)
        {
            foreach (byte b in bytes)
            {
                Console.Write("{0:X} ", b);
            }
            Console.WriteLine();
        }

        public static void Main()
        {
            string password = "My secret password!";
            byte[] key = Encoding.UTF8.GetBytes(password);
            byte[] inputFileBytes = ReadInputFile(FileToEncode);
            RC4(ref inputFileBytes, key);
            WriteOutputFile(EncodedFileName, inputFileBytes);

            byte[] encodedBytes = ReadInputFile(EncodedFileName);
            RC4(ref encodedBytes, key);
            WriteOutputFile(DecodedFileName, encodedBytes);
        }
    }
}
